home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / TIMER.C < prev    next >
C/C++ Source or Header  |  1989-09-07  |  4KB  |  185 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "proc.h"
  5. #ifdef    MSDOS
  6. #include "pc.h"
  7. #endif
  8. #ifdef    AMIGA
  9. #include "amiga.h"
  10. #endif
  11.  
  12. static struct timer *Timers;    /* Head of running timer chain */
  13. int32 Clock;
  14.  
  15. void
  16. timerproc(i,v1,v2)
  17. int i;
  18. void *v1,*v2;
  19. {
  20.     register struct timer *t;
  21.     register struct timer *expired = NULLTIMER;
  22.     char i_state;
  23.  
  24.     for(;;){
  25.         i_state = dirps();    /* Tick is modified by an interrupt */
  26.         while(Tick == 0)
  27.             pwait(&Tick);
  28.         Tick--;
  29.         restore(i_state);
  30.  
  31.         Clock++;
  32.         systick();    /* Machine-dependent per-tick stuff */
  33.  
  34.         /* Decrement the first timer. If it expires,
  35.          * take it off the running list and put it
  36.          * on a singly linked list of expired timers
  37.          */
  38.         if(Timers != NULLTIMER)
  39.             Timers->count--;
  40.         else
  41.             continue;    /* Nothing else on this tick */
  42.  
  43.         while(Timers != NULLTIMER && Timers->count <= 0){
  44.             if(Timers->next == Timers){
  45.                 printf("PANIC: Timer loop at %lx\n",
  46.                  (long)Timers);
  47.                 iostop();
  48.                 exit(1);
  49.             }
  50.             /* Save Timers since stop_timer will change it */
  51.             t = Timers;
  52.             stop_timer(t);
  53.             t->state = TIMER_EXPIRE;
  54.             /* Add to expired timer list */
  55.             t->next = expired;
  56.             expired = t;
  57.         }
  58.         /* Now go through the list of expired timers, removing each
  59.          * one and kicking the notify function, if there is one
  60.          */
  61.         while((t = expired) != NULLTIMER){
  62.             expired = t->next;
  63.             if(t->func){
  64.                 (*t->func)(t->arg);
  65.             }
  66.         }
  67.     }
  68. }
  69. /* Start a timer */
  70. void
  71. start_timer(t)
  72. struct timer *t;
  73. {
  74.     register struct timer *tnext,*tprev;
  75.     int32 tot;
  76.  
  77.     if(t == NULLTIMER)
  78.         return;
  79.     if(t->state == TIMER_RUN)
  80.         stop_timer(t);
  81.     if(t->start == 0)
  82.         return;        /* A start value of 0 disables the timer */
  83.  
  84.     t->state = TIMER_RUN;
  85.     /* Find right place on list for this guy */
  86.     tot = 0;
  87.     tprev = NULLTIMER;
  88.     for(tnext = Timers;tnext != NULLTIMER;tnext = tprev->next){
  89.         if(tnext->count + tot > t->start)
  90.             break;
  91.         tprev = tnext;
  92.         tot += tnext->count;
  93.     }
  94.     /* At this point, tprev points to the entry that should go right
  95.      * before us, and tnext points to the entry just after us. Either or
  96.      * both may be null.
  97.      */
  98.     t->count = t->start - tot;    /* Adjust for entries before us */
  99.     if((t->prev = tprev) == NULLTIMER)
  100.         Timers = t;        /* Put at beginning */
  101.     else
  102.         tprev->next = t;
  103.  
  104.     if((t->next = tnext) != NULLTIMER){
  105.         tnext->prev = t;
  106.         /* Adjust the following entry's count */
  107.         tnext->count -= t->count;
  108.     }
  109. }
  110. /* Stop a timer */
  111. void
  112. stop_timer(t)
  113. register struct timer *t;
  114. {
  115.     register struct timer *tp;
  116.  
  117.     if(t == NULLTIMER)
  118.         return;
  119.     if(t->state == TIMER_RUN){
  120.         /* Delete from active timer list */
  121.         if(t->next != NULLTIMER)
  122.             t->next->prev = t->prev;
  123.         if(t->prev != NULLTIMER)
  124.             t->prev->next = t->next;
  125.         else
  126.             Timers = t->next;
  127.         /* Adjust count for the next timer */
  128.         if((tp = t->next) != NULLTIMER)
  129.             tp->count += t->count;
  130.     }
  131.     t->state = TIMER_STOP;
  132. }
  133. /* Return count of ticks remaining on this timer */
  134. int32
  135. read_timer(t)
  136. struct timer *t;
  137. {
  138.     register struct timer *tp;
  139.     int32 tot;
  140.  
  141.     if(t->state != TIMER_RUN)
  142.         return 0;
  143.  
  144.     tot = 0;
  145.     for(tp = Timers;tp != NULLTIMER; tp = tp->next){
  146.         tot += tp->count;
  147.         if(tp == t)
  148.             break;
  149.     }
  150.     return tot;
  151. }
  152. /* Delay process for specified number of ticks */
  153. void
  154. pause(ticks)
  155. int32 ticks;
  156. {
  157.     if(Curproc == NULLPROC || ticks == 0)
  158.         return;
  159.     alarm(ticks);
  160.     /* The actual event doesn't matter, since we'll be alerted */
  161.     while(Curproc->alarm.state == TIMER_RUN && pwait(Curproc) == 1)
  162.         ;
  163.  
  164.     alarm(0L); /* Make sure it's stopped, in case we were killed */    
  165. }
  166. static void
  167. t_alarm(x)
  168. void *x;
  169. {
  170.     alert((struct proc *)x,1);
  171. }
  172. /* Send signal to current process after specified number of ticks */
  173. void
  174. alarm(ticks)
  175. int32 ticks;
  176. {
  177.     if(Curproc != NULLPROC){
  178.         Curproc->alarm.start = ticks;
  179.         Curproc->alarm.func = t_alarm;
  180.         Curproc->alarm.arg = (char *)Curproc;
  181.         start_timer(&Curproc->alarm);
  182.     }
  183. }
  184.     
  185.